package com.dingreading.cloud.admin.controller;

import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.admin.dto.ShopCartSendDto;
import com.dingreading.cloud.admin.entity.*;
import com.dingreading.cloud.admin.service.*;
import com.dingreading.cloud.admin.util.bean.PurchaseUtil;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.google.common.collect.Lists;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/system/whStockOut/virtual")
@Api(tags = "总部-仓库出库管理（非实体商品）V2")
public class WhStockOutVirtualController {

    @Resource
    protected WhStockInService whStockInService;
    @Resource
    protected WhStockOutService whStockOutService;
    @Resource
    protected WhStockOutGoodsService whStockOutGoodsService;
    @Resource
    protected WhStockOutGoodsLogService whStockOutGoodsLogService;
    @Resource
    protected OrderFormService orderFormService;
    @Resource
    protected ShopCartService shopCartService;
    @Resource
    protected GoodsWetPriceService goodsWetPriceService;


    @ApiOperation(value = "分页列表")
    @PostMapping(value = "/pageList", produces = "application/json; charset=UTF-8")
    public R<Object> pageList(
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "订单号/商品名/商品规格名") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "状态 1.待发货 4.出库完成 ") @RequestParam(value = "status", required = false) Integer status
    ) {
        Page<ShopCartSendDto> page = this.shopCartService.outPageListV2(pageUtil, keyword, 2, status);

        PageBeanDto data = new PageBeanDto();
        data.setTotal(page.getTotalRow());
        data.setList(page.getRecords());
        return R.ok(data);
    }


    @ApiOperation(value = "更新出库备注")
    @PostMapping(value = "/updateOutRemark", produces = "application/json; charset=UTF-8")
    public R<Object> updateOutRemark(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "商品订单号") @RequestParam(value = "code") String code,
            @ApiParam(value = "购物车id") @RequestParam(value = "shopCartId") Long shopCartId,
            @ApiParam(value = "出库备注") @RequestParam(value = "remark") String remark
    ) {
        ShopCart shopCart = shopCartService.getByCodeAndId(code, shopCartId);
        if (shopCart == null) R.fail("购物车商品获取失败");
        if (!shopCart.getStatus().equals(EnumType.ShopCart.PAYED.getType()))
            return R.fail("购物车商品状态错误当前状态：" + EnumType.ShopCart.getStatus(shopCart.getStatus()));

        OrderForm form = orderFormService.getByCode(null, code);
        String resultMsg = judgeOrderFormStatus(form);
        if (StringUtils.isNotBlank(resultMsg))
            return R.fail(resultMsg);

        boolean l = shopCartService.updateOutRemark(code, shopCartId, remark);
        if (!l) return R.fail("更新出库备注失败");

        return R.ok();
    }


    @ApiOperation(value = "验证商品出库")
    @PostMapping(value = "/authGoodsOut", produces = "application/json; charset=UTF-8")
    public R<Object> authGoodsOut(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "商品订单号") @RequestParam(value = "code") String code,
            @ApiParam(value = "购物车id") @RequestParam(value = "shopCartId") Long shopCartId
    ) {
        ShopCart shopCart = shopCartService.getByCodeAndId(code, shopCartId);
        if (shopCart == null)
            R.fail("购物车商品获取失败");
        if (!shopCart.getStatus().equals(EnumType.ShopCart.PAYED.getType()))
            return R.fail("购物车商品状态错误当前状态：" + EnumType.ShopCart.getStatus(shopCart.getStatus()));

        OrderForm form = orderFormService.getByCode(null, code);
        String resultMsg = judgeOrderFormStatus(form);
        if (StringUtils.isNotBlank(resultMsg))
            return R.fail(resultMsg);

        JSONObject jsonObject = JsonUtil.toJsonObject(shopCart);
        // 库存是否足够
        boolean usable = true;
        // 出库数量
        Integer num = NepUtil.nullToZero(shopCart.getBuyNum());
        // 查询该商品符合出库数量的入库记录
        int usableNumCnt = whStockInService.getGoodsTypeUsableNum(shopCart.getGoodsTypeId());
        if (usableNumCnt < num) {
            usable = false;
        }
        // 剩余的库存数量
        jsonObject.put("usableNum", usableNumCnt);

        if (usable) {
            return R.ok(jsonObject);
        } else {
            return R.fail(4001, "用于出库的商品剩余库存不足", jsonObject);
        }
    }


    @ApiOperation(value = "非实体商品完成出库")
    @PostMapping(value = "/setOutOk", produces = "application/json; charset=UTF-8")
    public R<Object> setOutOk(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "商品订单号") @RequestParam(value = "code") String code,
            @ApiParam(value = "购物车id") @RequestParam(value = "shopCartId") Long shopCartId,
            @ApiParam(value = "备注") @RequestParam(value = "remark") String remark
    ) throws Exception {
        if (StringUtils.isBlank(code))
            return R.fail("请传递订单编号");
        if (null == shopCartId)
            return R.fail("请传递购物车记录id");
        if (StringUtils.isBlank(remark))
            return R.fail("请填写备注");

        ShopCart shopCart = shopCartService.getByCodeAndId(code, shopCartId);
        if (shopCart == null)
            return R.fail("购物车商品获取失败");
        if (!shopCart.getStatus().equals(EnumType.ShopCart.PAYED.getType()))
            return R.fail("购物车商品状态错误当前状态：" + EnumType.ShopCart.getStatus(shopCart.getStatus()));

        OrderForm form = orderFormService.getByCode(null, code);
        String resultMsg = judgeOrderFormStatus(form);
        if (StringUtils.isNotBlank(resultMsg))
            return R.fail(resultMsg);

        // 出库数量
        int outNum = NepUtil.nullToZero(shopCart.getBuyNum());

        // 获取商品的加权平均价
        GoodsWetPrice goodsWetPrice = goodsWetPriceService.getByGoodsIdAndGoodsTypeId(shopCart.getGoodsId(), shopCart.getGoodsTypeId());
        if (goodsWetPrice == null)
            return R.fail("商品的加权平均价获取失败");
        if (goodsWetPrice.getUsableNum() < outNum)
            return R.fail("库存数量不足，不能出库");
        double wetAvgPrice = NepUtil.nullToZero(goodsWetPrice.getWetAvePrice());

        // 查询该商品符合出库数量的入库记录
        List<WhStockIn> stockInList = whStockInService.getOkGoodsTypeUsableNumLog(shopCart.getGoodsTypeId(), outNum);
        if (CollectionUtils.isEmpty(stockInList))
            return R.fail("库存数量不足，不能出库");


        String timeStr = DateUtil.getNowDatetimeStr();
        // 出库单号
        String outCode = KitUtil.getOutCode();
        // 获取入库记录关联的采购商品记录
        Map<Long, Integer> updateStockInMap = new HashMap<>();
        List<WhStockOutGoodsLog> stockOutGoodsLogList = new ArrayList<>();

        // 新增出库单
        WhStockOut data = PurchaseUtil.newWhStockOut(
                headStaffUid, headStaffName, outCode, code, outNum, 1, 1, "出库完成",
                form.getName(), form.getPhone(), form.getAddress(), 2, remark, 0);
        // 新增出库的商品记录
        WhStockOutGoods stockOutGoods = PurchaseUtil.newWhStockOutGoods(
                headStaffUid, headStaffName, shopCart, outCode, code, outNum, 1, "出库完成", wetAvgPrice
        );

        for (WhStockIn stockIn : stockInList) {
            if (outNum > 0) {
                Integer usableNum = NepUtil.nullToZero(stockIn.getUsableNum());
                int updateNum = 0;
                if (usableNum >= outNum) {
                    // 该入库记录的可用库存数足够
                    updateNum = outNum;
                    // 更新扣除入库记录的出库数
                    outNum = 0;
                } else {
                    // 不够，减去可用入库数得到最新的出库数
                    updateNum = usableNum;
                    // 更新扣除入库记录的出库数
                    outNum -= usableNum;
                }

                // 计算入库记录要消耗的数量
                Integer integer = updateStockInMap.get(stockIn.getId());
                if (integer == null)
                    // 存入要消耗的库存数量
                    updateStockInMap.put(stockIn.getId(), updateNum);
                else
                    // 更新要消耗的库存数量
                    updateStockInMap.put(stockIn.getId(), updateNum + NepUtil.nullToZero(integer));

                // 新增出库商品使用的入库记录
                WhStockOutGoodsLog log = PurchaseUtil.newWhStockOutGoodsLog(shopCart, code, outCode, stockIn, headStaffUid, headStaffName, updateNum);
                stockOutGoodsLogList.add(log);
            }
        }

        // 保存出库单和出库商品记录
        whStockOutService.saveOrUpdate(data);
        whStockOutGoodsService.saveOrUpdate(stockOutGoods);
        // 保存出库商品记录使用的入库记录
        whStockOutGoodsLogService.saveOrUpdateBatch(stockOutGoodsLogList);

        // 更新入库记录的可用库存数
        int i = whStockInService.updateUsableNum(updateStockInMap, timeStr);
        if (i <= 0)
            throw new Exception("更新入库记录的库存数量失败");

        // 购物车记录设置出库完成
        boolean l = shopCartService.setOutOk(code, shopCartId, remark);
        if (!l)
            throw new Exception("出库完成设置失败");

        // 商品订单状态更新为发货中
//        orderFormService.updateSending(form.getCode());

        // 更新商品的加权平均价、剩余金额、剩余数量
        // 获取商品的库存数量
        Map<Long, Integer> newStockNumMap = whStockInService.getStockNumMap(Lists.newArrayList(shopCart.getGoodsTypeId()));
        int stockNum = newStockNumMap.get(goodsWetPrice.getGoodsTypeId());
        double usablePrice = DoubleUtil.mul(stockNum, goodsWetPrice.getWetAvePrice());
        boolean w = goodsWetPriceService.updateUsableNumAndUsablePrice(goodsWetPrice.getId(), shopCart.getGoodsTypeId(),
                stockNum, usablePrice);
        if (!w)
            throw new Exception("商品的加权平均价更新失败");

        // 获取订单关联的购物车商品（实体/非实体）有没有没出库
        long waitOutCnt = shopCartService.getWaitOutCnt(code);
        // 订单关联的购物车商品（实体/非实体）全部出库完成，设置订单完成
        if (waitOutCnt == 0)
            orderFormService.setOk(code);

        return R.ok();
    }

    /**
     * 判断订单状态和关联状态
     */
    private String judgeOrderFormStatus(OrderForm form) {
        if (form == null)
            return "订单获取失败";
        if (!form.getStatus().equals(EnumType.OrderForm.WAIT_SEND.getType()) && !form.getStatus().equals(EnumType.OrderForm.SENDING.getType()))
            return "商品订单状态不符合订单状态：" + EnumType.OrderForm.getStatus(form.getStatus());

        return "";
    }

}